package com.charging.business.utils;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

public class DateEx extends Date {
    private static final long serialVersionUID = 1L;
    public static String version = "2024051001";

    public DateEx() {
        super();
    }

//	public DateEx(long date)
//	{
//		super(date);
//	}

    /**
     * 获取默认格式字符串时间的格式
     *
     * @param stDefault - 默认格式字符串时间, 默认格式：
     *                  "yyyy-MM-dd HH:mm:ss"
     *                  "yyyy-MM-dd HH:mm:ss.SSS"
     *                  "yyyy-MM-ddTHH:mm:ss"
     *                  "yyyy-MM-ddTHH:mm:ss.SSS"
     * @return - 默认时间格式
     */
    static String defaultPattern(String stDefault) {
        String pattern = "";
        stDefault = stDefault.toUpperCase();
        if (stDefault.indexOf("T") >= 0) {// 含T
            if (stDefault.indexOf(".") >= 0) {// 含毫秒时间
                pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS";
            } else {// 不含毫秒时间
                pattern = "yyyy-MM-dd'T'HH:mm:ss";
            }
        } else {// 不含T
            if (stDefault.indexOf(".") >= 0) {// 含毫秒时间
                pattern = "yyyy-MM-dd HH:mm:ss.SSS";
            } else {// 不含毫秒时间
                pattern = "yyyy-MM-dd HH:mm:ss";
            }
        }
        return pattern;
    }

    public static DateEx make() {
        return new DateEx();
    }

    public static DateEx make(Date dt) {
        DateEx ret = new DateEx();
        ret.setTime(dt.getTime());
        return ret;
    }

    /**
     * 依据已有Date,构造特定Data
     * 样例，获取当天的午夜时间：
     * <pre>
     * 	Date dt = new Date();
     * 	DateEx midnight =  DateEx.make(dt,"yyyy-MM-dd 00:00:00.000");
     * 	</pre>
     *
     * @param dt
     * @param pattern - 格式
     * @return
     */
    public static DateEx make(Date dt, String pattern) {
        String st = DateEx.dt2Str(dt, pattern);

        return DateEx.make(st, pattern);
    }

    public static DateEx make(java.sql.Date dt) {
        DateEx ret = new DateEx();
        ret.setTime(dt.getTime());
        return ret;
    }

    public static DateEx make(String st, String pattern) {
        DateEx ret = new DateEx();
        ret.parse(st, pattern);
        return ret;
    }

    /**
     * 默认格式字符串时间转DateEx时间
     *
     * @param st - 默认格式字符串时间, 默认格式:
     *           "yyyy-MM-dd HH:mm:ss"
     *           "yyyy-MM-dd HH:mm:ss.SSS"
     *           "yyyy-MM-ddTHH:mm:ss"
     *           "yyyy-MM-ddTHH:mm:ss.SSS"
     * @return
     */
    public static DateEx make(String st) {
        return make(st, defaultPattern(st));
    }

    /**
     * 根据Unix时间构造DateEx
     *
     * @param ut - 距离1970-01-01 08:00:00的秒数
     * @return
     */
    public static DateEx make(int ut) {
        long milliseconds = Integer.toUnsignedLong(ut) * 1000;
        DateEx ret = new DateEx();
        ret.setTime(milliseconds);
        return ret;
    }

    /**
     * 根据毫秒时间构造DateEx
     *
     * @param milliseconds - 距离1970-01-01 08:00:00的毫秒数
     * @return
     */
    public static DateEx make(long milliseconds) {
        DateEx ret = new DateEx();
        ret.setTime(milliseconds);
        return ret;
    }

    public static DateEx now(int secAfter) {
        DateEx ret = new DateEx();
        return ret.someTime(secAfter);
    }

    public static DateEx make(java.sql.Timestamp timestamp) {
        DateEx ret = new DateEx();
        ret.setTime(timestamp.getTime());
        return ret;
    }

    public static int now2Int(String pattern) {
        return DateEx.make(new Date()).toInt(pattern);
    }

    /**
     * 按默认格式返回当前日期时间
     *
     * @return - 输出格式："yyyy-MM-dd HH:mm:ss"
     */
    public static String now2str() {
        return now2str("yyyy-MM-dd HH:mm:ss", "GMT+08:00");
    }

//	public static String now2Str(String pattern)
//	{
//		return DateEx.make(new Date()).toString(pattern);
//	}
//
//	public static String now2Str()
//	{
//		return now2Str("yyyy-MM-dd HH:mm:ss");
//	}

    /**
     * 按给定格式返回当前日期时间
     *
     * @param pattern - 输出格式
     * @return
     */
    public static String now2str(String pattern) {
        return now2str(pattern, "GMT+08:00");
    }

    /**
     * 按给定格式返回当前日期时间
     *
     * @param pattern - 日期时间格式,如"yyyy-MM-dd HH:mm:ss"
     * @return
     */
    public static String now2str(String pattern, String timeZone) {
        String ret = "";
        if (pattern == null || pattern == "") {pattern = "yyyy-MM-dd HH:mm:ss";}
        if (timeZone == null || timeZone == "") {timeZone = "GMT+08:00";}

        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        sdf.setTimeZone(TimeZone.getTimeZone(timeZone));

        ret = sdf.format(new Date());

        return ret;
    }

    /**
     * 返回当前Unix时间
     * 本地时区
     *
     * @return - 当前时间距离1970-01-01 08:00:00的秒数
     * @since 2024051001
     */
    public static long now2ut() {
        return new Date().getTime() / 1000;
    }

    /**
     * 返回当前毫秒Unix时间
     * 本地时区
     *
     * @return - 当前时间距离1970-01-01 08:00:00的毫秒数
     * @since 2024051001
     */
    public static long now2ms() {
        return new Date().getTime();
    }

    /**
     * Date转Unix时间
     *
     * @param dt - Date时间
     * @return - 距1970-01-01 08:00:00的秒数
     * @since - 2024051001
     */
    public static long dt2ut(Date dt) {
        return dt.getTime() / 1000;
    }

    /**
     * Unix时间转Data
     *
     * @param ut - 距1970-01-01 08:00:00的秒数
     * @return
     * @since - 2024051001
     */
    public static Date ut2dt(int ut) {
        long milliseconds = Integer.toUnsignedLong(ut) * 1000;
        return new Date(milliseconds);
    }

    /**
     * 获取整秒Date
     *
     * @param dt - 需要转换的Date
     * @return - 整秒Date
     */
    public static Date dt2Sdt(Date dt) {
        long lt = (dt.getTime() / 1000) * 1000;

        return new Date(lt);
    }

    /**
     * Date转字符串
     *
     * @param dt
     * @param pattern - 输出格式
     * @return
     */
    public static String dt2Str(Date dt, String pattern) {
        return DateEx.make(dt).toString(pattern);
    }

    /**
     * Date转字符串
     *
     * @param dt
     * @return - 输出格式："yyyy-MM-dd HH:mm:ss"
     */
    public static String dt2Str(Date dt) {
        return dt2Str(dt, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 字符串时间转UNIX时间(1970-1-1 0:0:0距今的秒数)
     *
     * @param st      - 字符串时间
     * @param pattern - 如"yyyy-MM-dd HH:mm:ss"或"yyyy-MM-dd HH:mm:ss SSS"
     * @return
     */
    public static long str2ut(String st, String pattern) {
        DateEx dt = make(st, pattern);

        return dt.dt2ut();
    }

    /**
     * 默认格式字符串时间转UNIX时间(1970-1-1 0:0:0距今的秒数)
     *
     * @param st - 默认格式字符串时间
     *           "yyyy-MM-dd HH:mm:ss"
     *           "yyyy-MM-dd HH:mm:ss.SSS"
     *           "yyyy-MM-ddTHH:mm:ss"
     *           "yyyy-MM-ddTHH:mm:ss.SSS"
     * @return
     */
    public static long str2ut(String st) {
        return str2ut(st, defaultPattern(st));
    }

    /**
     * Unix时间转字符串
     *
     * @param ut      - 距1970-01-01 08:00:00的秒数
     * @param pattern - 输出格式
     * @return
     * @since 2024051001
     */
    public static String ut2str(int ut, String pattern) {
        return DateEx.make(ut).toString(pattern);
    }

//  2024-05-10废除, 用ut2str(int ut,String pattern)替代
//	public static String ut2Str(long ut,String pattern)
//	{
//		return DateEx.make(ut).toString(pattern);
//	}

    /**
     * Unix时间转字符串
     *
     * @param ut
     * @return - 输出格式："yyyy-MM-dd HH:mm:ss"
     */
    public static String ut2str(int ut) {
        return DateEx.make(ut).toString("yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 毫秒时间转字符串
     *
     * @param ms      - 距1970-01-01 08:00:00的毫秒数
     * @param pattern - 输出格式
     * @return
     * @since 2024051001
     */
    public static String ms2str(long ms, String pattern) {
        return DateEx.make(ms).toString(pattern);
    }

    /**
     * 字符串时间校验
     *
     * @param st      - 字符串时间
     * @param pattern - 时间格式
     * @return
     */
    public static boolean chkValid(String st, String pattern) {
        DateEx dt = DateEx.make(st, pattern);
        String tt = dt.toString(pattern);
        return tt.equals(st);
    }

    /**
     * 长整形时间校验
     *
     * @param ms      - 样例：20240501120101999
     * @param pattern - 格式
     * @return
     */
    public static boolean chkValid(long ms, String pattern) {
        String st = Long.toUnsignedString(ms);
        return chkValid(st, pattern);
    }

    /**
     * 整形时间校验
     *
     * @param ut      - 样例：2024050112
     * @param pattern - 格式
     * @return
     */
    public static boolean chkValid(int ut, String pattern) {
        long ms = Integer.toUnsignedLong(ut);
        return chkValid(ms, pattern);
    }

    public static String toString(Date dt, String pattern) {
        return make(dt).toString(pattern);
    }

    public static String toString(Date dt) {
        return make(dt).toString();
    }

    public static int toInt(Date dt, String pattern) {
        return make(dt).toInt(pattern);
    }

    public static Date someMonth(Date dt, int months) {
        DateEx dtx = DateEx.make(dt);

        return dtx.someMonth(months).toDate();
    }

    public static Date someDay(Date dt, int days) {
        DateEx dtx = DateEx.make(dt);

        return dtx.someDay(days).toDate();
    }

    public static Date someTime(Date dt, int seconds) {
        DateEx dtx = DateEx.make(dt);

        return dtx.someTime(seconds).toDate();
    }

    public static long msDiffer(Date o1, Date o2) {
        return make(o1).msDiffer(o2);
    }

    public static long msDifferABS(Date o1, Date o2) {
        return make(o1).msDifferABS(o2);
    }

    public static long ssDiffer(Date o1, Date o2) {
        return make(o1).ssDiffer(o2);
    }

    public static long ssDifferABS(Date o1, Date o2) {
        return make(o1).ssDifferABS(o2);
    }

    public static long dsDiffer(Date o1, Date o2) {
        return make(o1).dsDiffer(o2);
    }

//	2024-05-10废除, 用dt2ut替换	
//	public long toUnixTime()
//	{
//		return getTime()/1000;
//	}
//	2024-05-10废除, 用dt2ut(Date dt)替换
//	public static long toUnixTime(Date dt)
//	{
//		return make(dt).toUnixTime();
//	}

    public static long dsDifferABS(Date o1, Date o2) {
        return make(o1).dsDifferABS(o2);
    }

    public static int mthDiffer(Date o1, Date o2) {
        return make(o1).mthDiffer(o2);
    }

    public static int mthDiffer(DateEx o1, DateEx o2) {
        return o1.mthDiffer(o2);
    }

    public static int mthDifferABS(Date o1, Date o2) {
        return make(o1).mthDifferABS(o2);
    }

    public static int mthDifferABS(DateEx o1, DateEx o2) {
        return o1.mthDifferABS(o2);
    }

    public static Date toMidNight(Date dt, boolean begin) {
        return make(dt).toMidNight(begin).toDate();
    }

    public static DateEx dayBefore(int days) {
        DateEx ret = new DateEx();

        return ret.someDay(-days);
    }

    public static DateEx dayAfter(int days) {
        DateEx ret = new DateEx();

        return ret.someDay(days);
    }

    public static List<String> between(Date dtSta, Date dtEnd, String pattern) {
        DateEx dtTmp = DateEx.make(dtSta);
        String cs = String.format("%s", dtTmp.toString(pattern));

        List<String> res = new ArrayList<>();
        res.add(cs);

        while (DateEx.toInt(dtEnd, pattern) > dtTmp.toInt(pattern)) {
            if (pattern.contains("ss")) {
                dtTmp = dtTmp.someTime(1);
            } else if (pattern.contains("mm")) {
                dtTmp = dtTmp.someTime(60);
            } else if (pattern.contains("HH")) {
                dtTmp = dtTmp.someTime(60 * 60);
            } else if (pattern.contains("dd")) {
                dtTmp = dtTmp.someDay(1);
            } else if (pattern.contains("MM")) {
                dtTmp = dtTmp.someMonth(1);
            } else {
                dtTmp = dtTmp.someMonth(12);
            }

            cs = String.format("%s", dtTmp.toString(pattern));
            if (!res.contains(cs)) {
                res.add(cs);
            }
        }

        return res;
    }

    /**
     * 返回时间据1970-01-01 00:00:00的天数
     *
     * @param dt
     * @return - 0 base index;
     */
    public static long days(Date dt) {
        Calendar cdt = Calendar.getInstance();
        cdt.setTime(dt);
        return (cdt.getTimeInMillis() + cdt.getTimeZone().getOffset(0)) / 1000 / 60 / 60 / 24;
    }

    /**
     * 解析日期时间字符串
     *
     * @param st       - 日期时间字符串
     * @param pattern  - 格式
     * @param timeZone - 时区
     */
    void parse(String st, String pattern, String timeZone) {
        if (pattern == null || pattern == "") {
            pattern = "yyyy-MM-dd HH:mm:ss";
        }
        if (timeZone == null || timeZone == "") {
            timeZone = "GMT+08:00";
        }

        try {//必须捕获异常
            SimpleDateFormat sdf = new SimpleDateFormat(pattern);
            sdf.setTimeZone(TimeZone.getTimeZone(timeZone));
            this.setTime(sdf.parse(st).getTime());
        } catch (Exception px) {
            this.setTime(new Date(0).getTime());
        }
    }

    /**
     * 按默认时区解析日期时间字符串
     * 默认时区为："GMT+08:00"
     *
     * @param st      - 日期时间字符串
     * @param pattern - 格式
     */
    void parse(String st, String pattern) {
        parse(st, pattern, "GMT+08:00");
    }

    /**
     * 当前时间转Unix时间
     *
     * @return - 距1970-01-01 08:00:00的秒数
     * @since - 2024051001
     */
    public long dt2ut() {
        return getTime() / 1000;
    }

    public Date toDate() {
        return new Date(this.getTime());
    }

    public String toString(String pattern, String timeZone) {
        String ret = "";
        if (pattern == null || pattern == "") {
            pattern = "yyyy-MM-dd HH:mm:ss";
        }
        if (timeZone == null || timeZone == "") {
            timeZone = "GMT+08:00";
        }

        try {//必须捕获异常
            SimpleDateFormat sdf = new SimpleDateFormat(pattern);
            sdf.setTimeZone(TimeZone.getTimeZone(timeZone));
            ret = sdf.format(getTime());
        } catch (Exception px) {
        }

        return ret;
    }

    public String toString(String pattern) {
        return toString(pattern, "GMT+08:00");
    }

    @Override
    public String toString() {
        return toString("yyyy-MM-dd HH:mm:ss", "GMT+08:00");
    }

    public java.sql.Date toSQLDate() {
        return new java.sql.Date(this.getTime());
    }

    public java.sql.Timestamp toTimestamp() {
        return new java.sql.Timestamp(this.getTime());
    }

    public int toInt(String pattern) {
        String cs = toString(pattern);

        return Integer.parseInt(cs);
    }

    public DateEx someMonth(int months) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(this);
        calendar.add(Calendar.MONTH, months);
        return DateEx.make(calendar.getTime());
    }

    public DateEx someDay(int days) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(this);
        calendar.add(Calendar.DATE, days);
        return DateEx.make(calendar.getTime());
    }

    public DateEx someTime(int seconds) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(this);
        calendar.add(Calendar.SECOND, seconds);
        return DateEx.make(calendar.getTime());
    }

    public long msDiffer(Date other) {
        return getTime() - other.getTime();
    }

    public long msDiffer(DateEx other) {
        return msDiffer(other.toDate());
    }

    public long msDifferABS(Date other) {
        return Math.abs(getTime() - other.getTime());
    }

    public long msDifferABS(DateEx other) {
        return msDifferABS(other.toDate());
    }

    public long ssDiffer(Date other) {
        return (getTime() - other.getTime()) / 1000;
    }

    public long ssDiffer(DateEx other) {
        return ssDiffer(other.toDate());
    }

    public long ssDifferABS(Date other) {
        return Math.abs((getTime() - other.getTime()) / 1000);
    }

    public long ssDifferABS(DateEx other) {
        return ssDifferABS(other.toDate());
    }

    public long dsDiffer(Date other) {
        long ut0 = this.getTime();
        long ut1 = other.getTime();
        return (ut0 - ut1) / 1000 / 60 / 60 / 24;
    }

    public long dsDiffer(DateEx other) {
        return dsDiffer(other.toDate());
    }

    public long dsDifferABS(Date other) {
        long ut0 = this.getTime();
        long ut1 = other.getTime();
        return Math.abs((ut0 - ut1) / 1000 / 60 / 60 / 24);
    }

    public long dsDifferABS(DateEx other) {
        return dsDifferABS(other.toDate());
    }

    public int mthDiffer(Date other) {
        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTime(other);

        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(this);

        int startYear = startCalendar.get(Calendar.YEAR);
        int startMonth = startCalendar.get(Calendar.MONTH);

        int endYear = endCalendar.get(Calendar.YEAR);
        int endMonth = endCalendar.get(Calendar.MONTH);

        int monthDifference = 0;

        if (startYear == endYear) {
            monthDifference = endMonth - startMonth;
        } else {
            monthDifference = (endYear - startYear) * 12 + endMonth - startMonth;
        }

        return monthDifference;
    }

    public int mthDiffer(DateEx other) {
        return mthDiffer(other.toDate());
    }

    public int mthDifferABS(Date other) {
        return Math.abs(this.mthDiffer(other));
    }

    public int mthDifferABS(DateEx other) {
        return Math.abs(this.mthDiffer(other));
    }

    public DateEx toMidNight(boolean begin) {
        if (begin) {
            return DateEx.make(toString("yyyy-MM-dd 00:00:00.000"));
        }

        return DateEx.make(toString("yyyy-MM-dd 23:59:59.999"));
    }

    /**
     * 返回当前时间距1970-01-01 00:00:00的天数
     *
     * @return - 0 base index;
     */
    public long days() {
        Calendar cdt = Calendar.getInstance();
        cdt.setTime(this);
        return (cdt.getTimeInMillis() + cdt.getTimeZone().getOffset(0)) / 1000 / 60 / 60 / 24;
    }
}
